#include <stdlib.h>

#include "lib.h"
#include "rdsql.h"
#include "rdgame.h"
#include "rdsaved.h"
#include "odbc.h"
#include "missinggamenums.h"

RedDogSQL::RedDogSQL(const String& DBDSN, const String& DBLogin, const String& DBPassword)
	: TrackSQL(DBDSN, DBLogin, DBPassword)
{
#ifdef USE_MISSINGGAMENUMS
	//missing game nums deleted in TrackSQL::~TrackSQL
	missinggamenums = new MissingGameNums(this, "pub_getTableIdentityRedDog");
#endif
}

int32
RedDogSQL::createGame(int32 casinoId,
	PID pid, bool8 forMoney, SESSIONID sessionId, int32 compFactor,
	RedDogGameID gid, int32 bet, int32* balance, int32* comp)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_CreateGameRedDog ");
		query->addParam(casinoId);
		query->addParam(pid);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(sessionId, ODBCQuery::NOQUOTES);
		query->addParam(compFactor);
		query->addParam(bet, ODBCQuery::MONEY);

		if (query->exec())
		{
			while (query->getRow())
			{
				ok =
					query->getData(1, gid, RDOG_GAMEID_SIZE) &&
					query->getData(2, balance, ODBCQuery::MONEY) &&
					query->getData(3, comp);
			}
		}
		delete query;
	}
	delete conn;

	if (ok)
	{
#ifdef USE_MISSINGGAMENUMS
		int32 gamenum = atol(gid);
		if (missinggamenums)
			missinggamenums->setGameNum(gamenum);
#endif
	}

	return ok ? NoError : ExecFailed;
}

int32
RedDogSQL::deal(int32 casinoId, PID pid, bool8 forMoney, RedDogGameID gid,
	int32 numPlayer, uint8* player, uint8 ending, int32 outcome,
	int32 balanceAdjust, int32* balance, int32* comp)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_RedDogDeal ");
		query->addParam(casinoId);
		query->addParam(pid);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam(player, 2, ODBCQuery::BINARY);
		query->addParam((int32)ending);

		if (numPlayer > 2)
			query->addParam(player + 2, numPlayer - 2, ODBCQuery::BINARY);
		else
			query->addParam((uint8)0, ODBCQuery::BINARY);

		query->addParam((uint8)(outcome & 0xffL), ODBCQuery::BINARY);
		query->addParam(balanceAdjust, ODBCQuery::MONEY);

		if (query->exec())
		{
			while (query->getRow())
			{
				ok = query->getData(1, balance, ODBCQuery::MONEY) &&
					query->getData(2, comp);
			}
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
RedDogSQL::gameDone(int32 casinoId, PID pid, bool8 forMoney, RedDogGameID gid, 
	uint8 ThirdCard, bool8 raised, int32 outcome,
	int32 balanceAdjust, int32* balance, int32* comp)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;
	
	query = conn->query();
	if (query)
	{
		query->define("exec pub_RedDogGameDone ");
		query->addParam(casinoId);
		query->addParam(pid);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam((bool8)(raised != 0));
		query->addParam(ThirdCard, ODBCQuery::BINARY);
		query->addParam((uint8)(outcome & 0xffL), ODBCQuery::BINARY);
		query->addParam(balanceAdjust, ODBCQuery::MONEY);

		if (query->exec())
		{
			while (query->getRow())
			{
				ok = query->getData(1, balance, ODBCQuery::MONEY) &&
					query->getData(2, comp);
			}
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
RedDogSQL::hasSavedGame(PID pid, bool8 forMoney, RedDogGameID gid,
	RedDogSavedGame* dest, bool8* exists)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	*exists = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_RedDogGetSavedGame ");
		query->addParam(pid);
		query->addParam((bool8)(forMoney != 0));

		if (query->exec())
		{
			int32 hasSaved = 0;
			int16 smallint;
			int32 numCards;

			ok = true;

			while (query->getRow())
			{
				if (query->getData(1, &hasSaved) && hasSaved)
				{
					*exists = true;

					query->getData(2, gid, RDOG_GAMEID_SIZE);

					query->getData(3, &dest->shue.seed);
					query->getData(4, &smallint);
					dest->shue.next = smallint;

					query->getData(5, &dest->bet, ODBCQuery::MONEY);

					query->getData(6, dest->playerCards,
						RedDogSavedGame::MAXCARDS, &numCards);

					ASSERT(numCards == RedDogSavedGame::MAXCARDS);
				}
			}
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
RedDogSQL::removeSavedGame(RedDogGameID gid)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;
	
	query = conn->query();
	if (query)
	{
		query->define("exec pub_RedDogRemoveSavedGame ");
		query->addParam(gid, ODBCQuery::NOQUOTES);

		if (query->exec())
		{
			ok = true;

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}

int32
RedDogSQL::saveGame(PID pid, bool8 forMoney, RedDogGameID gid,
	RedDogSavedGame* src)
{
	ODBCConnection* conn;
	ODBCQuery* query;
	bool8 ok = false;

	conn = getConn();
	if (!conn)
		return NoConnection;

	query = conn->query();
	if (query)
	{
		query->define("exec pub_RedDogSaveGame ");
		query->addParam(pid);
		query->addParam((bool8)(forMoney != 0));
		query->addParam(gid, ODBCQuery::NOQUOTES);
		query->addParam((int32)src->shue.seed);
		query->addParam(src->shue.next);

		if (query->exec())
		{
			ok = true;

			while (query->getRow())
				/* ignore */ ;
		}
		delete query;
	}
	delete conn;

	return ok ? NoError : ExecFailed;
}
